package parser;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;

/**
 * @Author:石小俊
 * @Date: 2022/12/26 10:12
 * @Version:1.0-SNAPSHOT
 * @Description: DOM解析
 */
public class DOMParser {

    public static void main(String[] args) {
        // 创建DOM工厂
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            // 通过DOM工厂获取对应的解析器
            DocumentBuilder builder = factory.newDocumentBuilder();

            // 开始解析
            // 此处的document表示的是当前XML文档,整个文档对象
            Document document = builder.parse(DOMParser.class.getClassLoader().getResourceAsStream("students.xml"));

            // 这是一种便捷属性，该属性允许直接访问文档的文档元素的子节点
            // 此处获取的是整个XML文档的子节点
            // 对于文档来说,其子节点即为文档内容的根元素
            // 此处即为class
            Element root = document.getDocumentElement();
            System.out.println("根标签:"+root.getTagName());
            // 获取指定属性名所对应的属性值
            String no = root.getAttribute("no");
            System.out.println("no属性值:"+no);
            // 获取指定元素所有的属性
            // 返回值是一个NamedNodeMap对象
            // 该对象可以当做List集合来使用
            NamedNodeMap attributes = root.getAttributes();
            // 其对象的getLength()方法相当于List的size()方法
            for(int i = 0; i < attributes.getLength(); i++){
                // item(i)方法相当于List的get(i)方法
                Node node = attributes.item(i);
                System.out.println(node);
            }

            // 获取指定标签的子节点
            // 其返回值也是一个类似于List集合的对象
            NodeList childNodes = root.getChildNodes();
            System.out.println("子节点数量:"+childNodes.getLength());
            for(int i = 0; i < childNodes.getLength();i++){
                // 遍历这些子节点,这些节点中包含文本节点与元素节点
                // 对于文本节点,只需要取值即可,无需解析
                // 对于元素节点,仍然需要进一步解析
                // 如何区分当前节点是什么类型的节点
                Node node = childNodes.item(i);
                // 通过getNodeType()方法获取当前节点类型
                // 通过Node提供的节点类型常量值进行判断
                if(node.getNodeType() == Node.ELEMENT_NODE){
                    // 如果当前节点是元素节点
//                    System.out.println("元素节点");
                    // 将当前节点强转为Element
                    Element ele = (Element) node;
                    System.out.println("元素名:"+ele.getTagName());
                    // 获取所有属性
                    NamedNodeMap stuAttrs = ele.getAttributes();
                    for(int j = 0; j < stuAttrs.getLength(); j++){
                        Node item = stuAttrs.item(j);
                        System.out.println(item);
                    }
                    // 获取当前元素的子节点
                }
                if(node.getNodeType() == Node.TEXT_NODE){
                    // 如果当前节点是文本节点
                    // 直接打印文本内容值
                    System.out.println("文本节点,文本内容为:"+node.getTextContent());
                }
            }

            // 根据解析后的数据进行操作
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
